﻿using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class USInternalCurve : ScriptableObject
{
    [SerializeField]
    private AnimationCurve animationCurve;
    [SerializeField]
    private float duration = 10f;
    private bool hasBeenModified;
    [SerializeField]
    private List<USInternalKeyframe> internalKeyframes = new List<USInternalKeyframe>();

    public USInternalKeyframe AddKeyframe(float time, float value)
    {
        USInternalKeyframe item = null;
        foreach (USInternalKeyframe keyframe2 in this.internalKeyframes)
        {
            if (Mathf.Approximately(keyframe2.Time, time))
            {
                item = keyframe2;
            }
            if (item != null)
            {
                break;
            }
        }
        if (item == null)
        {
            item = ScriptableObject.CreateInstance<USInternalKeyframe>();
            this.internalKeyframes.Add(item);
        }
        item.Time = time;
        item.Value = value;
        item.InTangent = 0f;
        item.OutTangent = 0f;
        item.curve = this;
        this.internalKeyframes.Sort(new Comparison<USInternalKeyframe>(this.KeyframeComparer));
        this.BuildAnimationCurveFromInternalCurve();
        return item;
    }

    public void BuildAnimationCurveFromInternalCurve()
    {
        while (this.animationCurve.keys.Length > 0)
        {
            this.animationCurve.RemoveKey(0);
        }
        Keyframe key = new Keyframe();
        foreach (USInternalKeyframe keyframe2 in this.Keys)
        {
            key.value = keyframe2.Value;
            key.time = keyframe2.Time;
            key.inTangent = keyframe2.InTangent;
            key.outTangent = keyframe2.OutTangent;
            this.animationCurve.AddKey(key);
        }
        this.HasBeenModified = true;
    }

    public void BuildInternalCurveFromAnimationCurve()
    {
        foreach (Keyframe keyframe in this.animationCurve.keys)
        {
            USInternalKeyframe keyframe2 = null;
            foreach (USInternalKeyframe keyframe3 in this.internalKeyframes)
            {
                if (Mathf.Approximately(keyframe.time, keyframe3.Time))
                {
                    keyframe2 = keyframe3;
                    break;
                }
            }
            if (keyframe2 != null)
            {
                keyframe2.ConvertFrom(keyframe);
            }
            else
            {
                USInternalKeyframe item = ScriptableObject.CreateInstance<USInternalKeyframe>();
                item.ConvertFrom(keyframe);
                item.curve = this;
                this.internalKeyframes.Add(item);
                this.internalKeyframes.Sort(new Comparison<USInternalKeyframe>(this.KeyframeComparer));
            }
        }
        this.HasBeenModified = true;
    }

    public float Evaluate(float time)
    {
        return this.animationCurve.Evaluate(time);
    }

    public USInternalKeyframe GetNextKeyframe(USInternalKeyframe keyframe)
    {
        if (this.internalKeyframes.Count == 0)
        {
            return null;
        }
        if (this.internalKeyframes[this.internalKeyframes.Count - 1] == keyframe)
        {
            return null;
        }
        int num = -1;
        for (int i = 0; i < this.internalKeyframes.Count; i++)
        {
            if (this.internalKeyframes[i] == keyframe)
            {
                num = i;
            }
            if (num != -1)
            {
                break;
            }
        }
        return this.internalKeyframes[num + 1];
    }

    public USInternalKeyframe GetPrevKeyframe(USInternalKeyframe keyframe)
    {
        if (this.internalKeyframes.Count == 0)
        {
            return null;
        }
        if (this.internalKeyframes[0] == keyframe)
        {
            return null;
        }
        int num = -1;
        for (int i = 0; i < this.internalKeyframes.Count; i++)
        {
            if (this.internalKeyframes[i] == keyframe)
            {
                num = i;
            }
            if (num != -1)
            {
                break;
            }
        }
        return this.internalKeyframes[num - 1];
    }

    private int KeyframeComparer(USInternalKeyframe a, USInternalKeyframe b)
    {
        return a.Time.CompareTo(b.Time);
    }

    public void RemoveKeyframe(USInternalKeyframe internalKeyframe)
    {
        for (int i = this.internalKeyframes.Count - 1; i >= 0; i--)
        {
            if (this.internalKeyframes[i] == internalKeyframe)
            {
                this.internalKeyframes.RemoveAt(i);
            }
        }
        this.internalKeyframes.Sort(new Comparison<USInternalKeyframe>(this.KeyframeComparer));
        this.BuildAnimationCurveFromInternalCurve();
    }

    public void ValidateKeyframeTimes()
    {
        for (int i = this.Keys.Length - 1; i >= 0; i--)
        {
            if ((i != (this.Keys.Length - 1)) && Mathf.Approximately(this.Keys[i].Time, this.Keys[i + 1].Time))
            {
                this.internalKeyframes.Remove(this.Keys[i]);
            }
        }
    }

    public float Duration
    {
        get
        {
            return this.duration;
        }
        set
        {
            this.duration = value;
        }
    }

    public float FirstKeyframeTime
    {
        get
        {
            if (this.internalKeyframes.Count == 0)
            {
                return 0f;
            }
            return this.internalKeyframes[0].Time;
        }
    }

    public bool HasBeenModified
    {
        get
        {
            return this.hasBeenModified;
        }
        set
        {
            this.hasBeenModified = value;
        }
    }

    public USInternalKeyframe[] Keys
    {
        get
        {
            return this.internalKeyframes.ToArray();
        }
    }

    public float LastKeyframeTime
    {
        get
        {
            if (this.internalKeyframes.Count == 0)
            {
                return this.Duration;
            }
            return this.internalKeyframes[this.internalKeyframes.Count - 1].Time;
        }
    }

    public AnimationCurve UnityAnimationCurve
    {
        get
        {
            return this.animationCurve;
        }
        set
        {
            this.animationCurve = new AnimationCurve();
            foreach (Keyframe keyframe in value.keys)
            {
                this.animationCurve.AddKey(keyframe);
            }
            this.BuildInternalCurveFromAnimationCurve();
        }
    }
}

